/**
 * Class GroupsModule.
 * 
 * @author Maxime Ollagnier
 */
GroupsModule.inherits(Module);
function GroupsModule() {
	var that = this;
	
	this.table = undefined;
	this.group = undefined;
	
	/** Table */
	this.table = new TableModule({
		'selectable' : true,
		'onSelect' : function(id) {
			that.edit(id);
		}
	});
	this.table.id = 'groupTable';
	this.table.columnList.push(new Column('name', I18n.get('name'), '65%', true));
	this.table.columnList.push(new Column('userType', I18n.get('user.type'), '30%', true));
	var deleteCol = new Column('delete', '', '5%', false, true);
	deleteCol.clickable = false;
	deleteCol.getText = function(object) {
		if (!UserManager.hasRoles(['MANAGE_PROFILE'])) {
			return '';
		}
		return $('<i class="icon-remove icon" />').click(function() {
			that.remove(object.id);
		});
	};
	this.table.columnList.push(deleteCol);
	
	/** Input Modules */
	this.inputName = new InputTextModule({
		'id' : 'inputName',
		'label' : I18n.get('name'),
		'placeholder' : I18n.get('name'),
		'mandatory' : true,
		'validationPattern' : ValidationPattern.VALID_DEFAULT,
		'validationMethod' : new ValidationMethod({
			'errorMessage' : I18n.get('user.group.name.exists'),
			'method' : function(value) {
				var unique = true;
				that.table.objectMap.foreach(function(id, group) {
					unique = unique && (that.group.id == group.id || group.name != value);
				});
				return unique;
			}
		}),
		'onKeyUp' : function() { that.setJQFormTitle(); },
		'onEnter' : function() { that.save(); }
	});
	this.inputUserType = new InputSelectModule({
		'id' : 'inputUserType',
		'label' : I18n.get('type'),
		'options' : EnumManager.UserType,
		'mandatory' : true,
		'getText' : function(value, role) {
			return Util.checkStringNotEmpty(value) ? I18n.get('UserType.' + value) : value;
		},
		'onChange' : function() {
			that.updateAvailableRoles();
		},
		'defaultValue' : ''
	});
	this.inputRole = new InputSelectModule({
		'id' : 'inputRole',
		'size' : 20,
		'multiple' : true,
		'getText' : function(value, role) {
			return value;
		}
	});
	this.inputRole.id = 'inputRole';
	this.inputRoleAvailable = new InputSelectModule({
		'id' : 'inputRoleAvailable',
		'size' : 20,
		'multiple' : true,
		'getText' : function(value, role) {
			return value;
		}
	});
	this.inputRoleAvailable.id = 'inputRoleAvailable';
}

GroupsModule.neededRoles = ['MANAGE_PROFILE'];

GroupsModule.prototype.fillJQ = function(jQ) {
	var that = this;
	
	// List title
	jQ.append($('<h5>' + I18n.get('user.group.list') + '</h5>'));
	
	// New button
	if (UserManager.hasRoles(['MANAGE_PROFILE'])) {
		var buttonNew = $('<div class="btn new">' + I18n.get('new') + ' <i class="icon-plus icon"/></div>');
		buttonNew.click(function() { that.addNew(); });
		jQ.find('h5:first').append(buttonNew);
	}
	
	// List
	jQ.append(this.table.buildJQ());
	
	// Edition form
	this.jQForm = $('<div id="editionForm"></div>').hide();
	jQ.append(this.jQForm);
	
	// Fills form with selected object
	if (Util.checkObject(this.table.selectedObject)) {
		this.edit(this.table.selectedObject.id);
	}
};

/**
 * Fills the JQ representation of the edition form
 */
GroupsModule.prototype.fillJQForm = function() {
	var that = this;
	
	// Form title
	this.setJQFormTitle();
	
	// Form
	var form = $('<div class="form well"></div>');
	this.jQForm.append(form);

	var jQNameRow = $('<div class="row-fluid"></div>');
	var columnLeft = $('<div class="span6"></div>');
	columnLeft.append(this.inputName.buildJQ());
	var columnRight = $('<div class="span6"></div>');
	columnRight.append(this.inputUserType.buildJQ());
	form.append(jQNameRow.append(columnLeft).append(columnRight));
	
	form.append($('<hr/>'));
	
	var jQRolesRow = $('<div class="row-fluid"></div>');
	var column0 = $('<div class="span1"></div>');
	var column1 = $('<div class="span4"></div>');
	column1.append(I18n.get('user.group.roles'));
	column1.append(this.inputRole.buildJQ());
	var column2 = $('<div class="span2"></div>');
	column2.append($('<div><i class="icon-arrow-left icon" title="' + I18n.get('add') + '" /></div>').click(function() { that.addRoles(); }));
	column2.append($('<div><i class="icon-arrow-right icon" title="' + I18n.get('remove') + '" /></div>').click(function() { that.removeRoles(); }));
	var column3 = $('<div class="span4"></div>');
	column3.append(I18n.get('user.roles.available'));
	column3.append(this.inputRoleAvailable.buildJQ());
	var column4 = $('<div class="span1"></div>');
	form.append(jQRolesRow.append(column0).append(column1).append(column2).append(column3).append(column4));
	
	var buttonRow = $('<div class="btn-row"></div>');
	form.append(buttonRow);
	var buttonSave = $('<div class="btn save">' + I18n.get('save') + '</div>');
	buttonSave.click(function() { that.save(); });
	buttonRow.append(buttonSave);
};

/**
 * Sets the edition form title
 */
GroupsModule.prototype.setJQFormTitle = function() {
	var jQFormTitle = this.jQForm.children('h5:first');
	if (!Util.checkJQueryNotEmpty(jQFormTitle)) {
		jQFormTitle = $('<h5></h5>');
		this.jQForm.prepend(jQFormTitle);
	}
	jQFormTitle.clear();
	if (!Util.check(this.group.id)) {
		jQFormTitle.text(I18n.get('user.group.new'));
	} else {
		jQFormTitle.text(I18n.get('user.group') + ' - ' + this.group.name);
	}
	if (this.isModified()) {
		jQFormTitle.addClass('modified');
		jQFormTitle.append(' *');
	} else {
		jQFormTitle.removeClass('modified');
	}
};

/**
 * Returns true if any modification of in the edition form is pending
 */
GroupsModule.prototype.isModified = function() {
	return this.inputName.modified || this.inputRole.modified;
};

/**
 * Loads the data
 */
GroupsModule.prototype.loadData = function(callback) {
	var that = this;
	
	// Resets the table object map
	this.table.objectMap = new Map();
	
	// Fills the table
	$.each(UserManager.groups, function(id, group) {
		that.table.objectMap.put(id, group);
	});
	
	Util.getFunction(callback)();
};

/**
 * Sets the edited object
 */
GroupsModule.prototype.setGroup = function(group) {
	group = Util.getObject(group);
	if (this.group != group) {
		this.group = group;
		
		this.inputName.modified = false;
		this.inputUserType.modified = false;
		this.inputRole.modified = false;
		
		this.inputName.setValue(this.group.name);
		this.inputUserType.setValue(this.group.userType);
		this.inputRole.setOptions(Object.sortByValue(this.group.roles, UserManager.compareRoles), true);
		
		this.inputUserType.setReadonly(Util.check(this.group.id));
	}
	this.updateAvailableRoles();
	this.validate();
};

/**
 * Update the available roles depending on the roles and the selected userType
 */
GroupsModule.prototype.updateAvailableRoles = function() {
	var that = this;
	var availableRoles = Util.checkStringNotEmpty(this.inputUserType.value) ? UserManager.getRoles(this.inputUserType.value) : {};
	var filteredRoles = {};
	$.each(availableRoles, function(availableRoleName, availableRole) {
		var contains = false;
		$.each(that.inputRole.options, function(roleName, role) {
			if (availableRoleName == roleName) {
				contains = true;
				return true;
			}
		});
		if (!contains) {
			filteredRoles[availableRoleName] = availableRole;
		}
	});
	filteredRoles = Object.sortByValue(filteredRoles, UserManager.compareRoles);
	this.inputRoleAvailable.setOptions(filteredRoles, true).buildJQ();
};

/**
 * Edit a new object
 */
GroupsModule.prototype.addNew = function() {
	this.table.unselect();
	this.setGroup();
	this.jQForm.clear();
	this.fillJQForm();
	this.jQForm.show();
};

/**
 * Edit an object
 */
GroupsModule.prototype.edit = function(id) {
	this.jQForm.clear();
	if (!Util.check(id)) {
		this.jQForm.hide();
		return;
	}
	this.setGroup(UserManager.groups[id]);
	this.fillJQForm();
	this.jQForm.show();
};

GroupsModule.prototype.addRoles = function() {
	// This is a workaround to an HTML bug : when you select several entries of a select
	// and you unpress the mouse button outside the select, the onChange event is not triggered...
	this.inputRoleAvailable.getJQ().find('select:first').trigger('change');
	var selectedAvailableRoleNames = this.inputRoleAvailable.value;
	var roles = this.inputRole.options;
	var availableRoles = this.inputRoleAvailable.options;
	for (var i = 0; i < selectedAvailableRoleNames.length; i++) {
		roles[selectedAvailableRoleNames[i]] = this.inputRoleAvailable.options[selectedAvailableRoleNames[i]];
		delete availableRoles[selectedAvailableRoleNames[i]];
	}
	roles = Object.sortByValue(roles, UserManager.compareRoles);
	availableRoles = Object.sortByValue(availableRoles, UserManager.compareRoles);
	this.inputRole.setOptions(roles, true).buildJQ();
	this.inputRoleAvailable.setOptions(availableRoles, true).buildJQ();
	this.inputRole.modified = true;
	this.setJQFormTitle();
};

GroupsModule.prototype.removeRoles = function() {
	// This is a workaround to an HTML bug : when you select several entries of a select
	// and you unpress the mouse button outside the select, the onChange event is not triggered...
	this.inputRole.getJQ().find('select:first').trigger('change');
	var selectedRoleNames = this.inputRole.value;
	var availableRoles = this.inputRoleAvailable.options;
	var roles = this.inputRole.options;
	for (var i = 0; i < selectedRoleNames.length; i++) {
		availableRoles[selectedRoleNames[i]] = this.inputRole.options[selectedRoleNames[i]];
		delete roles[selectedRoleNames[i]];
	}
	availableRoles = Object.sortByValue(availableRoles, UserManager.compareRoles);
	roles = Object.sortByValue(roles, UserManager.compareRoles);
	this.inputRoleAvailable.setOptions(availableRoles, true).buildJQ();
	this.inputRole.setOptions(roles, true).buildJQ();
	this.inputRole.modified = true;
	this.setJQFormTitle();
};

/**
 * Saves an object
 */
GroupsModule.prototype.save = function() {
	if(!this.validate()) {
		return;
	}
	
	this.group.name = this.inputName.value;
	this.group.roles = this.inputRole.options;
	
	var that = this;
	AjaxManager.getJSON('saveGroup', {
		'group' : JSON.stringify(this.group)
	}, function(result) {
		if (result.success) {
			UserManager.groups = result.groups;
			that.table.selectedObject = undefined;
			$.each(UserManager.groups, function(id, group) {
				if (group.name == that.group.name) {
					that.table.selectedObject = group;
				}
			});
			that.reload();
		}
	});
	return true;
};

/**
 * Removes an object
 */
GroupsModule.prototype.remove = function(id) {
	var that = this;
	var selectedObject = this.table.selectedObject;
	AjaxManager.getJSON('removeGroup', {
		'id' : id
	}, function(result) {
		if (result.success) {
			UserManager.groups = result.groups;
			that.table.selectedObject = undefined;
			if (Util.checkObject(selectedObject)) {
				$.each(UserManager.groups, function(id, group) {
					if (group.name == selectedObject.name) {
						that.table.selectedObject = group;
					}
				});
			}
			that.reload();
		}
	});
	return true;
};
